package org.appmon.core.config;

import java.io.IOException;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.Modifier;
import javassist.NotFoundException;

public class ByteCodeModifier {
	
	public byte[] modify(String className,String classpath) throws CannotCompileException, NotFoundException, IOException{
		
		System.out.println("CTST "+ClassPool.class.getClassLoader());
		ClassPool cp = ClassPool.getDefault();
		cp.insertClassPath(classpath);
	 	System.out.println("CTPOOL "+cp.hashCode());
        CtClass cc = cp.get(className);
        System.out.println("CCPOOL "+cc.hashCode());
        CtMethod[] ms=cc.getDeclaredMethods();
        
        System.out.println("Bypass check 1");
        StringBuilder mapCode=new StringBuilder();
        
        for(CtMethod cm:ms){			        	
        	String varname=(cc.getName()+"."+cm.getName()+"."+"Counter").replace('.', '_');			        	
        	CtField f = new CtField(CtClass.longType,varname, cc);        	
        	f.setModifiers(Modifier.STATIC);			        	
        	cc.addField(f,CtField.Initializer.byExpr("0L"));			        	
        	cm.insertBefore(varname+"++;"); 
        	System.out.println("Bypass check 2");
        	mapCode.append("\"");
        	mapCode.append(varname);     
        	mapCode.append("~");
        	mapCode.append("\"");        	
        	mapCode.append("+");
        	mapCode.append(varname);
        	System.out.println("Bypass check 3");
        	if(cm!=ms[ms.length-1]){
        		mapCode.append("+");
        		mapCode.append("\":\"");
        		mapCode.append("+");
			}
        	System.out.println(mapCode.toString());			        	
        }
        System.out.println("Bypass check 4");
        CtMethod method = CtNewMethod.make("public static String getAllCount() {  return "+mapCode.toString() +"; }", cc);
        cc.addMethod(method);               
       cc.detach();
        System.out.println("Bypass check 5");
		return cc.toBytecode();
	}

}
